package Dimensionnement;

import Dimensionnement.*;
import hibernate.*;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.math.*;


import net.sf.hibernate.HibernateException;

public class CalculDimensionnement {

	//private static Logger logger = Logger.getLogger(CalculDimensionnement.class
		//	.getName());

	public int Nb_jour_Mois(Calendar calendar) {

		// dernier jour du mois
		@SuppressWarnings("static-access")
		int dateTo = calendar.getActualMaximum(calendar.DAY_OF_MONTH);

		return dateTo;
	}

	
	/**
	 * Calcul la difference entre un historique et prévision 
	 * @param s
	 * @param p
	 * @param d
	 * @return
	 * @throws HibernateException
	 */
	public int difference_prev_hist(int s, int p, Date d)
			throws HibernateException {
		

		TraitementDonnees donnee = new TraitementDonnees();

		int prev = donnee.recuperer_prevision(s, p, d);
		int hist = donnee.recuperer_Historique(s, p, d);
		if (prev == -1 || hist == -1) {
			//logger.warning(" impossible de recupérer les prev et historique les données saisies ne sont pas disponible - site - produit pour cette date ");
			return -1;
		}
		//System.out.println("-------la difference en prev-histooooo ======"
				//+ (prev - hist));
		if (prev - hist < 0)
			return -(prev - hist);
		return (prev - hist);

	}
	
	
	/**
	 * fonction importante elle crée les series de calcul
	 * @param d
	 * @param fin
	 * @return
	 */

	public List<Date> serie(Date d, Date fin) {

		
		List<Date> serie = new ArrayList<Date>();

			int moisd = d.getMonth();
			int anneed = d.getYear();
			int j = 0;
			Date dat = d;
			int a = anneed;
			int m = moisd;

			while (dat.compareTo(fin) < 0) {
				dat = new Date(a, m, 1);

				serie.add(j, dat);

				// des fois le jours est plus grand il passe
				if (dat.compareTo(fin) > 0) {

					dat = new Date(2999, 12, 9);
				}

				j++;
				m++;
				if (m > 11) {
					a++;
					m = 0;

				}
			

		}
		//System.out.println("la serie des date ======" + serie.toString());
		return serie;

	}

	/**
	 * Renvoi la list des difference entre les prevision et l'historique
	 * 
	 * @param d
	 * @param f
	 * @param s
	 * @param p
	 * @return
	 * @throws HibernateException
	 */
	public List<Integer> difference_serie(Date d, Date f, int s, int p)
			throws HibernateException {
		//System.out
			//	.println("-------calcul dans la serie de la difference ======site"
					//	+ s + "produit=" + p + "date=" + d);
        int differ = 0;
		List<Integer> dif = new ArrayList<Integer>();
		List<Date> date = serie(d, f);
		if (d != null && f != null && date != null) {

			for (int i = 0; i < date.size(); i++) {
				differ = difference_prev_hist(s, p, date.get(i));

				if (differ != -1)
					dif.add(differ);
				
			}
			return dif;
		}

		//logger.warning("Impossible  de créer les période valeur null");

		return dif;

	}

	public List<Integer> historique_serie(Date d, Date f, int s, int p)
			throws HibernateException {
		//System.out
			//	.println("-------calcul dans la consomation moyenne ======site"
					//	+ s + "produit=" + p + "date=" + d);
         int hist = 0;
		List<Integer> conso_moy = new ArrayList<Integer>();
		TraitementDonnees donne = new TraitementDonnees();
		List<Date> date = serie(d, f);
		int res;
		if (d != null && f != null && date != null) {

			for (int i = 0; i < date.size(); i++) {
				res = donne.recuperer_Historique(s, p, date.get(i));
				if (res != -1) {
					conso_moy.add(res);
					//System.out.println("la consomation pour ce site =" + res);
				}
			}
			return conso_moy;
		}

		//logger.warning("Impossible  de créer les période valeur null");

		return conso_moy;

	}
	
	public int consomation_moyenne(Date d, Date f, int s ,  int p) throws HibernateException
	{
		List<Integer> conso = historique_serie(d, f, s, p);
		int somme = 0;
		for(int i =0;i<conso.size();i++)
		{
			somme = somme+conso.get(i);
		}
		
		if(conso.size() >0)
		return (somme/conso.size())/4;
		return -1;
	}

	public List<Integer> Difference_serie_Maille(Date d, Date f, int s, int p,
			int Maille) throws HibernateException {
	//	System.out.println("-------integrer la maille ======site" + s
			//	+ "produit=" + p + "date=" + d + "la mailllle =" + Maille
			//	+ "--------");

		List<Integer> serie = difference_serie(d, f, s, p);
		List<Integer> serieMaille = new ArrayList<Integer>();
		int i = 0;
		int j = 0;
		int n = 0;

		if (serie != null) {
			while (serie.iterator().hasNext() && n < serie.size() * Maille) {

				for (i = n; i < Maille + n; i++) {
					if (serie.size() > j)
						serieMaille.add(i, serie.get(j) / Maille);

				}
				j++;
				n = i;

			}
			return serieMaille;
		}

		//logger.warning("Impossible de couper en maille la période -- valeur nulle");
		return serieMaille;
	}

	public double ecartType(List<Integer> n) {
		//System.out
				//.println("---------------calcul de l'ecartType --------------------"
						//+ n.toString());

		Double moy = (double) 0;
		Double som = (double) 0;
		List<Double> dif = new ArrayList<Double>();
		Double ecartType = (double) 0.;
		double nb = 0.;

		if (n != null) {
			for (int y = 0; y < n.size(); y++) {
				som = som + n.get(y);
				nb = nb + 1.;

			}
			if (nb > 0) {
				moy = (double) (som / nb);
				
				for (int j = 0; j < nb; j++) {

					dif.add(Math.pow(n.get(j) - moy, 2));
					ecartType = ecartType + dif.get(j);
				}

				if (ecartType / nb > 0 || ecartType / nb == 0) {
					Double r = Math.sqrt(ecartType / nb);
					
			//	System.out.println("ecart type ===" + ecartType
					//	+ "racine=====" + r);
					return r;
				}
				return Math.sqrt(-(ecartType / nb));
			}
		}
		//logger.warning("les périoe de calcule sont null -- calcul de l'écart type impossible"
			//	+ (-1));
	//	System.out
			//	.println("ecart type = -1 nb =" + nb + "n.size()=" + n.size());
		return (double) -1;

	}

	// SS = σ *coefficient de sécurité*racine carré(T+D)

	/**
	 * @param d
	 * @param f
	 * @param s
	 * @param p
	 * @param Maille
	 * @param taux
	 * @return
	 * @throws HibernateException
	 */
	public List<Double> CalculDimentionnement(Date d, Date f, int s, int p,
			String Maille, double taux) throws HibernateException {

		/*System.out
				.println("------------calcul dimentionnement---------------site="
						+ s
						+ " produit=="
						+ p
						+ "--entre date=="
						+ d
						+ "--et date = "
						+ f
						+ "--taux=="
						+ taux
						+ "--maille="
						+ Maille);*/

		List<Double> resultat = new ArrayList<Double>();

		int Maillemois = 1;
		int MailleJour = 1;
		if (Maille.equals("semaine")) {
			Maillemois = 4;
			MailleJour = 6;
		}

		if (Maille.equals("jour")) {
			Maillemois = 30;
			MailleJour = 1;
		}

		if (Maille.equals("mois")) {
			Maillemois = 1;
			MailleJour = 24;
		}

		List<Integer> serie = Difference_serie_Maille(d, f, s, p, Maillemois);
		
		//System.out.println("la seris ="+serie.toString());
		double ecart = ecartType(serie);

		//  racine ecart total
		if (serie != null) {

			
			
			//un ecart minimum en cas ou le calcul

			if (ecart == 0) {
				ecart = 0.1;
			}
			
			
			    Double race = racineTPlusD(s, p, MailleJour);
			    if(race!=null)
			    if (race <= 0) {
			    	race = 0.1;
				}
				
				
				
				if (race != null && ecart != -1) {
					resultat.add(race);
					resultat.add(ecart);
					
					resultat.add((ecart * taux * race));
					return resultat;
				
			}
			
			return null;
		} else
		//	logger.warning("Impossible de faire le calcul du stock -- les période sont nulles ");

		return null;

	}

	// r c'est la maille
	public Double racineTPlusD(int s, int p, int r) throws HibernateException {
		TraitementDonnees donne = new TraitementDonnees();
		int n = donne.recuperer_D(s, p);
		int m = donne.recuperer_T(s, p);
		Double ri = Double.parseDouble("" + r);
		Double ni = Double.parseDouble("" + n);
		Double mi = Double.parseDouble("" + m);

		if (n > 0 && m > 0) {
			return (Double) Math.sqrt(ni / ri + mi / ri);
		} else {
			//System.out.println("la racineee est null pas de d + T");
			return (Double) null;
		}

	}

	public Date petiteDate(int s, int p) throws HibernateException {
		List<Date> d = dateCommune(s, p);
		Date date = new Date(3000, 12, 28);

		for (int i = 0; i < d.size(); i++)

		{
			if (date.compareTo(d.get(i)) > 0)
				date = d.get(i);

		}

		return date;

	}

	public Date grandeDate(int s, int p) throws HibernateException {
		List<Date> d = dateCommune(s, p);
		Date date = new Date(1000, 12, 28);

		for (int i = 0; i < d.size(); i++)

		{
			if (date.compareTo(d.get(i)) < 0)
				date = d.get(i);

		}

		return date;

	}

	public List<Date> dateCommune(int s, int p) throws HibernateException {
		TraitementDonnees donne = new TraitementDonnees();
		List<HistoriqueVentes> histo = donne.recuperer_ToutesHisto(s, p);
		List<Prevision> prev = donne.recuperer_ToutesPrev(s, p);
		List<Date> dates = new ArrayList<Date>();
		for (int i = 0; i < histo.size(); i++) {
			for (int j = 0; j < prev.size(); j++) {

				if (histo.get(i).getDate().equals(prev.get(i).getDate()))
					dates.add(histo.get(i).getDate());
			}

		}

		return dates;

	}

}
